package cn.elwy.rcp.ui.progress;

import java.lang.reflect.InvocationTargetException;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.elwy.common.exception.RunException;
import cn.elwy.rcp.core.model.ui.progress.RunnableAdapter;

/**
 * 自定义运行状态类
 * @author HSQ
 */
public class RunnableWithProgress implements IRunnableWithProgress {

  private final Logger logger = LoggerFactory.getLogger(RunnableWithProgress.class);

  private int totalWork = IProgressMonitor.UNKNOWN; // 任务个数
  private int sleep; // 睡眠时间
  private String taskName; // 任务名称
  private RunnableAdapter method; // 执行的方法
  private int status;
  private Throwable error;
  private String errorMsg;
  private boolean canceled;
  private ProgressThread thread;

  public RunnableWithProgress(RunnableAdapter method) {
    this(method, "正在运行程序,请稍后...", IProgressMonitor.UNKNOWN, 100);
  }

  public RunnableWithProgress(RunnableAdapter method, String taskName) {
    this(method, taskName, IProgressMonitor.UNKNOWN, 100);
  }

  public RunnableWithProgress(RunnableAdapter method, String taskName, int totalWork) {
    this(method, taskName, totalWork, 100);
  }

  public RunnableWithProgress(RunnableAdapter method, String taskName, int totalWork, int sleep) {
    this.method = method;
    this.taskName = taskName;
    this.sleep = sleep;
    this.totalWork = totalWork;
    if (method == null) {
      String errorMsg = "MethodAdapter参数不能为空！";
      logger.error(errorMsg);
      throw new RunException(errorMsg);
    }
  }

  @Override
  public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
    monitor.beginTask(taskName, totalWork);
    try {
      thread = new ProgressThread(monitor);
      thread.start();
      while (thread.isAlive()) {
        try {
          if (monitor.isCanceled()) {
            thread.interrupt();
            break;
          }
          Thread.sleep(sleep);
        } catch (InterruptedException e) {
          logger.error(e.getMessage(), e);
        }
      }
      if (monitor.isCanceled()) {
        status = 1;
        throw new InterruptedException("请求已被用户中断！");
      }
    } catch (Exception e) {
      error = e;
      errorMsg = e.getMessage();
      logger.error(e.getMessage(), e);
    } finally {
      canceled = monitor.isCanceled();
      monitor.done();
    }
  }

  public boolean isCanceled() {
    return canceled;
  }

  public int getStatus() {
    return status;
  }

  public Throwable getError() {
    return error;
  }

  public String getErrorMsg() {
    return this.errorMsg;
  }

  public int getSleep() {
    return sleep;
  }

  public void setSleep(int sleep) {
    this.sleep = sleep;
  }

  public RunnableAdapter getMethod() {
    return method;
  }

  public void setMethod(RunnableAdapter method) {
    this.method = method;
  }

  public String getTaskName() {
    return taskName;
  }

  public void setTaskName(String taskName) {
    this.taskName = taskName;
  }

  public ProgressThread getThread() {
    return thread;
  }

  private class ProgressThread extends Thread {
    IProgressMonitor monitor;

    public ProgressThread(IProgressMonitor monitor) {
      this.monitor = monitor;
      String threadName = "Thread [" + this.getId() + "]";
      this.setName(threadName);
    }

    @Override
    public void run() {
      try {
        if (method != null) {
          method.run(monitor);
        }
      } catch (RunException e) {
        error = e;
        errorMsg = e.getMessage();
      } catch (Throwable e) {
        if (e.getMessage() == null) {
          e = new RunException(e.toString());
        }
        error = e;
        errorMsg = e.getMessage();
        logger.error(e.getMessage(), e);
      }
    }

  }

}
